package com.lizk.net.netty.base;

import java.util.concurrent.atomic.AtomicInteger;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class Server {

	EventLoopGroup bossGroup = new NioEventLoopGroup();
	EventLoopGroup workGroup = new NioEventLoopGroup();
	ServerBootstrap sb = new ServerBootstrap();
	AtomicInteger i = new AtomicInteger(0);

	public void bind(String ip, int port) {
		sb.group(bossGroup, workGroup)
		  .channel(NioServerSocketChannel.class)
		  .option(ChannelOption.SO_BACKLOG, 1024)
		  .childHandler(new ChileHandler());
		try {
			ChannelFuture f = sb.bind(ip, port).sync();
			f.channel().closeFuture().sync();

		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			bossGroup.shutdownGracefully();
			workGroup.shutdownGracefully();
		}
	}

	public class ChileHandler extends ChannelInitializer<SocketChannel> {
		@Override
		protected void initChannel(SocketChannel arg0) throws Exception {
			arg0.pipeline().addLast(new ServerHandler());
		}
	}

	public class ServerHandler extends ChannelInboundHandlerAdapter {

		@Override
		public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
			// 这里是用原始的ByteBuf作为传输数据的对象，但是会有粘包/拆包的问题。
			ByteBuf buf = (ByteBuf) msg;
			byte[] req = new byte[buf.readableBytes()];
			buf.readBytes(req);
			String body = new String(req, "utf-8");

			System.out.println(i.getAndIncrement() + "接受到消息：" + body);
			ByteBuf res = Unpooled.copiedBuffer((System.currentTimeMillis() + "").getBytes());
			ctx.write(res);
		}

		@Override
		public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
			ctx.flush();
		}

		@Override
		public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
			ctx.close();
		}

	}

	public static void main(String[] args) {
		Server s = new Server();
		s.bind("127.0.0.1", 10001);
	}
}
